package create_tenant

import (
	"context"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"git.mycaigou.com/gfyx/common/authorize"
	"git.mycaigou.com/gfyx/common/cache"
	"git.mycaigou.com/gfyx/common/tenant_db"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/common"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/remote/gfyx_oppty_service_remote"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/remote/omp_remote"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/tenant/create_tenant"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/tenant/tenant"
	micro_gfyx_oppty_service "git.mycaigou.com/gfyx/micro-gfyx-user-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/base"
	pb "git.mycaigou.com/gfyx/micro-gfyx-user-service/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service/tenant"
	"git.myscrm.cn/golang/stark/v4"
)

type CreateTenantService struct {
	tenantsRepository              tenant.TenantsRepositoryIface
	tenantsInstanceRepository      tenant.TenantsInstanceRepositoryIface
	tenantsProfitRepository        tenant.TenantsProfitRepositoryIface
	tenantsCreateTaskRepository    create_tenant.TenantsCreateTaskRepositoryIface
	tenantsCreateTaskLogRepository create_tenant.TenantsCreateTaskLogRepositoryIface
	tenantsCreateTjLogRepository   create_tenant.TenantsCreateTjLogRepositoryIface
	gfyxOpptyServiceRepository     gfyx_oppty_service_remote.GfyxOpptyServiceRepositoryIface
}

func NewCreateTenantService(
	tenantsRepository tenant.TenantsRepositoryIface,
	tenantsInstanceRepository tenant.TenantsInstanceRepositoryIface,
	tenantsProfitRepository tenant.TenantsProfitRepositoryIface,
	tenantsCreateTaskRepository create_tenant.TenantsCreateTaskRepositoryIface,
	tenantsCreateTaskLogRepository create_tenant.TenantsCreateTaskLogRepositoryIface,
	tenantsCreateTjLogRepository create_tenant.TenantsCreateTjLogRepositoryIface,
	gfyxOpptyServiceRepository gfyx_oppty_service_remote.GfyxOpptyServiceRepositoryIface,
) CreateTenantServiceIface {
	return &CreateTenantService{
		tenantsRepository:              tenantsRepository,
		tenantsInstanceRepository:      tenantsInstanceRepository,
		tenantsProfitRepository:        tenantsProfitRepository,
		tenantsCreateTaskRepository:    tenantsCreateTaskRepository,
		tenantsCreateTaskLogRepository: tenantsCreateTaskLogRepository,
		tenantsCreateTjLogRepository:   tenantsCreateTjLogRepository,
		gfyxOpptyServiceRepository:     gfyxOpptyServiceRepository,
	}
}

func (s *CreateTenantService) CreateTenant(ctx context.Context, request *pb.CreateTenantRequest) (*pb.CreateTenantResponse, error) {
	resp := &pb.CreateTenantResponse{
		TaskId: request.TaskId,
	}
	//token设置到缓存
	cacheKey := omp_remote.OmpServiceTokenCacheKey + request.TaskId
	redisClient, _ := cache.Redis()
	token, err := redisClient.Get(ctx, cacheKey)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取cache失败,key:%s,err:%s", cacheKey, err.Error())
	}
	if token == "" {
		_, err = redisClient.Set(ctx, cacheKey, request.Authorization, true, omp_remote.OmpServiceTokenCacheKeyMaxExpireTime)
		if err != nil {
			stark.Logger.Errorf(ctx, "设置cache失败,key:%s,err:%s", cacheKey, err.Error())
		}
	}

	//1、日志
	requestJSON, err := json.Marshal(request)
	if err != nil {
		stark.Logger.Errorf(ctx, "结构体转string,err:%s", err.Error())
	}
	tjLogId, err := s.saveTjLog(ctx, request.DeliveryNo, request.TaskId, request.Authorization, request.TenantCode, string(requestJSON), constants.CreateTenantTjTypeAdd)
	if err != nil {
		resp.Success = false
		return resp, err
	}
	//2、保存租户信息
	isNewTenant, tenantInstance, err := s.saveTenantInfo(ctx, request)
	if err != nil {
		resp.Success = false
		return resp, err
	}
	//3、保存租户任务信息
	_, err = s.saveCreateTaskLog(ctx, request)
	if err != nil {
		resp.Success = false
		return resp, err
	} else {
		resp.Success = true
	}
	//更新状态
	respJSON, err := json.Marshal(resp)
	_, err = s.tenantsCreateTjLogRepository.UpdateResponseStatus(ctx, tjLogId, constants.CreateTenantStatusSuccess, string(respJSON))
	if err != nil {
		stark.Logger.Errorf(ctx, "UpdateResponseStatus,err:%s", err.Error())
	}

	//异步开库
	go func() {
		_, err := s.createDatabaseSync(context.Background(), tjLogId, request.TenantCode, request.TaskId, tenantInstance, isNewTenant)
		if err != nil {
			stark.Logger.Errorf(ctx, "异步开库执行异常,err:%s", err.Error())
		}
		//更新admin密码
		if isNewTenant == true && request.InitPassword != "" {
			_, err = s.updateAdminPassword(context.Background(), request.TenantCode, request.InitPassword)
			if err != nil {
				stark.Logger.Errorf(ctx, "更新admin初始化密码,err:%s", err.Error())
			}
		}

	}()

	return resp, nil
}

// 更新admin密码
func (s *CreateTenantService) updateAdminPassword(ctx context.Context, tenantCode string, password string) (bool, error) {
	// 密钥16位，即AES-128，PKCS7填充模式
	ciphertext1Bytes, _ := hex.DecodeString(password)
	adminPwd, _ := utils.AesECBDecrypt(ciphertext1Bytes, []byte(utils.AesKey), utils.Pkcs7Padding)

	// 调用商机服务，更改admin密码，把租户code设置到上下文中，后面调用rpc方法时会用到
	ctx = context.WithValue(ctx, authorize.TENANT_CODE_KEY, tenantCode)
	ctx = context.WithValue(ctx, authorize.IgnoreProfit, "1") //忽略权益校验
	_, err := s.gfyxOpptyServiceRepository.UpdateAdminPassword(ctx, &micro_gfyx_oppty_service.UpdateAdminPasswordRequest{
		NewPassword: adminPwd,
	})
	if err != nil {
		stark.Logger.Errorf(ctx, "UpdateAdminPassword err:%s", err.Error())
	}
	return true, nil
}

// 异步执行开库操作
func (s *CreateTenantService) createDatabaseSync(ctx context.Context, tjLogId int32, tenantCode string, taskId string, tenantInstance *tenant.TenantsInstance, isNewTenant bool) (bool, error) {
	//1、创建数据库
	err := s.tenantsCreateTaskRepository.UpdateStatus(ctx, tenantCode, taskId, constants.CreateTenantStatusExecute)
	if err != nil {
		return false, err
	}
	_, err = s.createDatabaseCmd(ctx, tenantInstance, isNewTenant)
	if err != nil {
		return false, err
	}
	//2、更新状态
	err = s.tenantsCreateTaskRepository.UpdateStatus(ctx, tenantCode, taskId, constants.CreateTenantStatusSuccess)
	if err != nil {
		return false, err
	}
	//3、开库初始化：同步权益至租户库
	_, err = s.syncProfitToTenant(ctx, tenantCode)
	if err != nil {
		return false, err
	}
	//4、开库结果回调运营平台
	_, err = s.CreateTenantCallback(ctx, &pb.CreateTenantCallbackRequest{TaskId: taskId}, tjLogId)
	if err != nil {
		return false, err
	}
	return true, nil
}

func (s *CreateTenantService) syncProfitToTenant(ctx context.Context, tenantCode string) (bool, error) {
	// 把租户code设置到上下文中，后面调用rpc方法时会用到
	ctx = context.WithValue(ctx, authorize.TENANT_CODE_KEY, tenantCode)
	ctx = context.WithValue(ctx, authorize.IgnoreProfit, "1") //忽略权益校验
	profitList, err := s.tenantsProfitRepository.GetTenantsProfit(ctx, tenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTenantsProfit err:%s", err.Error())
	}
	saveTenantProfitData := make([]*micro_gfyx_oppty_service.SaveTenantProfitData, 0)
	for _, v := range profitList {
		saveTenantProfitData = append(saveTenantProfitData, &micro_gfyx_oppty_service.SaveTenantProfitData{
			ProfitCode:      v.ProfitCode,
			StartTime:       v.StartTime.Time.String()[0:19],
			EndTime:         v.EndTime.Time.String()[0:19],
			Number:          v.Number,
			DeliveryNo:      v.DeliveryNo,
			DeliveryBatchNo: v.DeliveryBatchNo,
			DeliveryAuthId:  v.DeliveryAuthId,
			CreatedBy:       v.CreatedBy,
		})
	}
	res, err := s.gfyxOpptyServiceRepository.SaveTenantProfit(ctx, &micro_gfyx_oppty_service.SaveTenantProfitRequest{
		ProfitList: saveTenantProfitData,
	})
	if err != nil {
		stark.Logger.Errorf(ctx, "SaveTenantProfit err:%s", err.Error())
	}
	return res.IsSuccess, nil
}

// 异步执行销户操作
func (s *CreateTenantService) removeDatabaseSync(ctx context.Context, tjLogId int32, tenantCode string, taskId string) (bool, error) {
	//开库结果回调运营平台
	_, err := s.CreateTenantCallback(ctx, &pb.CreateTenantCallbackRequest{TaskId: taskId}, tjLogId)
	if err != nil {
		return false, err
	}
	return true, nil
}

// 异步执行开库操作 阿里云sdk方式
func (s *CreateTenantService) createDatabase(ctx context.Context, tenantInstance *tenant.TenantsInstance) (bool, error) {
	//创建数据库
	createDbRes, err := common.NewAliyunDbClient().CreateDatabase(tenantInstance.DbName)
	if err != nil {
		stark.Logger.Errorf(ctx, "创建数据库失败,err:%s", err.Error())
	}
	fmt.Print(createDbRes)

	//创建用户
	tenantInstance.Password, err = utils.DecryptByAes(tenantInstance.Password)
	createAccountRes, err := common.NewAliyunDbClient().CreateAccount(tenantInstance.Username, tenantInstance.Password)
	if err != nil {
		stark.Logger.Errorf(ctx, "创建读写账号失败,err:%s", err.Error())
	}
	fmt.Print(createAccountRes)
	tenantInstance.ReaderPassword, err = utils.DecryptByAes(tenantInstance.ReaderPassword)
	createAccountReaderRes, err := common.NewAliyunDbClient().CreateAccount(tenantInstance.ReaderUsername, tenantInstance.ReaderPassword)
	if err != nil {
		stark.Logger.Errorf(ctx, "创建只读账号失败,err:%s", err.Error())
	}
	fmt.Print(createAccountReaderRes)

	//用户授权
	grantAccountPrivilegeRes, err := common.NewAliyunDbClient().GrantAccountPrivilege(tenantInstance.Username, tenantInstance.DbName, "ReadWrite")
	if err != nil {
		stark.Logger.Errorf(ctx, "授权账号权限失败,err:%s", err.Error())
	}
	grantAccountPrivilegeRes, err = common.NewAliyunDbClient().GrantAccountPrivilege(tenantInstance.ReaderUsername, tenantInstance.DbName, "ReadOnly")
	if err != nil {
		stark.Logger.Errorf(ctx, "授权账号权限失败,err:%s", err.Error())
	}
	fmt.Print(grantAccountPrivilegeRes)
	//备份数据库
	//还原数据库
	getAccountRes, err := common.NewAliyunDbClient().GetAccount(tenantInstance.Username)
	if err != nil {
		stark.Logger.Errorf(ctx, "查看账号失败,err:%s", err.Error())
	}
	fmt.Print(getAccountRes)
	return true, nil
}

// 异步执行开库操作 命令方式
func (s *CreateTenantService) createDatabaseCmd(ctx context.Context, tenantInstance *tenant.TenantsInstance, isNewTenant bool) (bool, error) {
	lastTaskLog, err := s.tenantsCreateTaskLogRepository.GetLastBatchTaskLog(ctx, tenantInstance.TenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetLastBatchTaskLog,err:%s", err.Error())
	}
	newBatchId := lastTaskLog.BatchId + 1
	//创建数据库
	newTaskLog := &create_tenant.TenantsCreateTaskLog{
		TenantCode: tenantInstance.TenantCode,
		BatchId:    newBatchId,
	}
	newTaskLog.Event = constants.CreateTaskLogEventCreateDatabase
	cmd, err := common.NewCreateDbCmd().CreateDatabase(ctx, tenantInstance.DbName)
	if err != nil {
		stark.Logger.Errorf(ctx, "创建数据库失败,err:%s", err.Error())
		newTaskLog.LogLevel = constants.CreateTaskLogLevelError
		newTaskLog.LogMsg = err.Error()
		errAdd := s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
		if errAdd != nil {
			stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
		}
		return false, err
	}
	newTaskLog.LogLevel = constants.CreateTaskLogLevelInfo
	newTaskLog.LogMsg = cmd
	errAdd := s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
	if errAdd != nil {
		stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
	}

	//创建账号和授权
	newTaskLog = &create_tenant.TenantsCreateTaskLog{
		TenantCode: tenantInstance.TenantCode,
		BatchId:    newBatchId,
	}
	newTaskLog.Event = constants.CreateTaskLogEventCreateAccountPrivilege
	userInfoList := make([]common.DbUserInfo, 0)
	tenantInstance.Password, err = utils.DecryptByAes(tenantInstance.Password)
	userInfoList = append(userInfoList, common.DbUserInfo{Username: tenantInstance.Username, Password: tenantInstance.Password, Privilege: common.PrivilegeReadWrite})
	tenantInstance.ReaderPassword, err = utils.DecryptByAes(tenantInstance.ReaderPassword)
	userInfoList = append(userInfoList, common.DbUserInfo{Username: tenantInstance.ReaderUsername, Password: tenantInstance.ReaderPassword, Privilege: common.PrivilegeReadOnly})
	cmd, err = common.NewCreateDbCmd().CreateAccount(ctx, userInfoList, tenantInstance.DbName)
	if err != nil {
		stark.Logger.Errorf(ctx, "创建数据库账号失败,err:%s", err.Error())
		newTaskLog.LogLevel = constants.CreateTaskLogLevelError
		newTaskLog.LogMsg = err.Error()
		errAdd := s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
		if errAdd != nil {
			stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
		}
		return false, err
	}
	newTaskLog.LogLevel = constants.CreateTaskLogLevelInfo
	newTaskLog.LogMsg = cmd
	errAdd = s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
	if errAdd != nil {
		stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
	}

	//备份
	if isNewTenant == true {
		newTaskLog = &create_tenant.TenantsCreateTaskLog{
			TenantCode: tenantInstance.TenantCode,
			BatchId:    newBatchId,
		}
		newTaskLog.Event = constants.CreateTaskLogEventCreateBackup
		cmd, err = common.NewCreateDbCmd().Backup(ctx, common.EmptyDatabaseName, tenantInstance.DbName)
		if err != nil {
			stark.Logger.Errorf(ctx, "创建备份失败,err:%s", err.Error())
			newTaskLog.LogLevel = constants.CreateTaskLogLevelError
			newTaskLog.LogMsg = err.Error()
			errAdd := s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
			if errAdd != nil {
				stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
			}
			return false, err
		}
		newTaskLog.LogLevel = constants.CreateTaskLogLevelInfo
		newTaskLog.LogMsg = cmd
		errAdd = s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
		if errAdd != nil {
			stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
		}
	}

	//恢复数据库
	if isNewTenant == true {
		newTaskLog = &create_tenant.TenantsCreateTaskLog{
			TenantCode: tenantInstance.TenantCode,
			BatchId:    newBatchId,
		}
		newTaskLog.Event = constants.CreateTaskLogEventRecoveryDatabase
		cmd, err = common.NewCreateDbCmd().Recovery(ctx, common.EmptyDatabaseName, tenantInstance.DbName)
		if err != nil {
			stark.Logger.Errorf(ctx, "恢复数据库失败,err:%s", err.Error())
			newTaskLog.LogLevel = constants.CreateTaskLogLevelError
			newTaskLog.LogMsg = err.Error()
			errAdd := s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
			if errAdd != nil {
				stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
			}
			return false, err
		}
		newTaskLog.LogLevel = constants.CreateTaskLogLevelInfo
		newTaskLog.LogMsg = cmd
		errAdd = s.tenantsCreateTaskLogRepository.AddTaskLog(ctx, newTaskLog)
		if errAdd != nil {
			stark.Logger.Errorf(ctx, "AddTenantsCreateTaskLog,err:%s", errAdd.Error())
		}
	}

	return true, nil
}

// 保存天际运营平台调用日志
func (s *CreateTenantService) saveTjLog(ctx context.Context, deliveryNo string, taskId string, authorization string, tenantCode string, requestJson string, logType int32) (int32, error) {
	tenantsCreateTjLog := &create_tenant.TenantsCreateTjLog{
		DeliveryNo:  deliveryNo,
		TaskId:      taskId,
		TenantCode:  tenantCode,
		Token:       authorization,
		Type:        logType,
		RequestData: requestJson,
	}
	autoId, err := s.tenantsCreateTjLogRepository.AddTenantsCreateTjLog(ctx, tenantsCreateTjLog)
	if err != nil {
		stark.Logger.Errorf(ctx, "AddTenantsCreateTjLog 新增天际开库调用日志,err:%s", err.Error())
	}

	return autoId, nil
}

func (s *CreateTenantService) saveTenantInfo(ctx context.Context, request *pb.CreateTenantRequest) (bool, *tenant.TenantsInstance, error) {
	//租户表
	isNewTenant := false
	tenants, err := s.tenantsRepository.GetTenantByCode(ctx, request.TenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTenantByCode,err:%s", err.Error())
	}
	if tenants == nil || tenants.Id == 0 {
		isNewTenant = true
		tenants.Code = request.TenantCode
		tenants.Name = request.TenantName
		tenants.Enabled = constants.TenantEnabled
		tenants.IsDeleted = constants.IsDeletedFalse
		tenants.MasterName = request.MasterName
		tenants.MasterPhone = request.MasterPhone
		tenants.MasterEmail = request.MasterEmail
		_, err := s.tenantsRepository.AddTenant(ctx, tenants)
		if err != nil {
			stark.Logger.Errorf(ctx, "AddTenant 新增租户,err:%s", err.Error())
		}
	}

	//租户产品表
	tenantsInstance, err := s.tenantsInstanceRepository.GetTenantsInstance(ctx, request.TenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTenantsInstance,err:%s", err.Error())
	}
	if tenantsInstance == nil || tenantsInstance.Id == 0 {
		tenantsInstance.TenantCode = request.TenantCode
		tenantsInstance.Host = stark.Configer.(stark.ApolloConfigerIface).GetStringValue("StarkMysql.Host", "") //测试环境是外网地址、预发布和生产环境是内网地址
		tenantsInstance.Port = 3306
		tenantsInstance.DbName = "gfyx_" + request.TenantCode

		tenantDbPwd := utils.CreateDbRandPwd(tenantsInstance.DbName)
		pwd, errPwd := tenant_db.EncryptByAes(tenantDbPwd) //AES加密，使用utils.DecryptByAes 解密
		if errPwd != nil {
			stark.Logger.Errorf(ctx, "生成AES密码失败,err:%s", errPwd.Error())
		}
		tenantsInstance.Password = pwd

		tenantsInstance.Username = tenantsInstance.DbName + "_rw"
		tenantsInstance.ReaderUsername = tenantsInstance.DbName + "_reader"
		tenantsInstance.ReaderPassword = pwd
		tenantsInstance.IsDeleted = constants.IsDeletedFalse
		_, err := s.tenantsInstanceRepository.AddTenantsInstance(ctx, tenantsInstance)
		if err != nil {
			stark.Logger.Errorf(ctx, "AddTenantsInstance 新增租户数据库实例,err:%s", err.Error())
		}
	}

	//租户权益
	tenantProfit := s.getProfitList(ctx, request)
	for _, item := range tenantProfit {
		if item.DeliveryNo != "" && item.DeliveryBatchNo != "" && item.DeliveryAuthId != "" {
			row, err := s.tenantsProfitRepository.ExistTenantProfit(ctx, item.DeliveryNo, item.DeliveryBatchNo, item.DeliveryAuthId)
			if err != nil {
				stark.Logger.Infof(ctx, "ExistTenantProfit,err:%s", err.Error())
			}
			if row.Id == 0 { //插入
				_, err := s.tenantsProfitRepository.AddTenantsProfit(ctx, item)
				if err != nil {
					stark.Logger.Infof(ctx, "AddTenantsProfit,err:%s", err.Error())
				}
			}
		}

	}
	if err != nil {
		stark.Logger.Infof(ctx, "保存租户权益 AddTenantsProfitBatch,err:%s", err.Error())
	}
	return isNewTenant, tenantsInstance, nil
}
func (s *CreateTenantService) getProfitList(ctx context.Context, request *pb.CreateTenantRequest) []*tenant.TenantsProfit {
	profitList := make([]*tenant.TenantsProfit, 0)
	for _, value := range request.AppAuths {
		for _, subValue := range value.Auths {
			if value.AppCode != "4022" && value.AppCode != "0000" { //排除系统管理、
				row := &tenant.TenantsProfit{
					TenantCode:      request.TenantCode,
					StartTime:       utils.StringToSqlTime(subValue.EffectiveStartTime),
					EndTime:         utils.StringToSqlTime(subValue.EffectiveEndTime),
					Number:          subValue.AuthNum,
					DeliveryBatchNo: request.DeliveryBatchNo,
					DeliveryNo:      request.DeliveryNo,
					DeliveryAuthId:  subValue.AuthId,
				}
				//天际产品code 与 供方营销产品code 映射枚举值
				switch value.ProductCode {
				case constants.OutProductCodeGfyx:
					row.ProfitCode = constants.ProductCodeMarketReport //市场洞察
					row.ProfitName = constants.ProductNameMarketReport
					break
				case constants.OutProductCodeClueProvince:
					row.ProfitCode = constants.ProductCodeClueRadarProvince //线索雷达省份版
					row.ProfitName = constants.ProductNameClueRadarProvince
					break
				case constants.OutProductCodeClueChannels:
					row.ProfitCode = constants.ProductCodeClueRadarProvince //线索雷达省份版
					row.ProfitName = constants.ProductNameClueRadarProvince
					break
				case constants.OutProductCodeClueNational:
					row.ProfitCode = constants.ProductCodeClueRadarNationwide //线索雷达全国版
					row.ProfitName = constants.ProductNameClueRadarNationwide
					break
				case constants.ProfitOutProductCodeAccount:
					row.ProfitCode = constants.ProductCodeUserAccount //单独账户购买
					row.ProfitName = constants.ProductNameUserAccount
					break
				case constants.ProfitOutProductCodeAiOutbound:
					row.ProfitCode = constants.ProductCodeAIOutbound //ai外呼
					row.ProfitName = constants.ProductNameAIOutbound
					break
				default:
					row.ProfitCode = ""
					break
				}
				//当SignType为2时，代表是续约产品,(1是新签，3是增购)
				// 获取该产品有效期最后的一条权益
				// 如果当前产品支持的日期比这个权益的开始时间更晚，那么就需要更改这个的开始时间。会导致这个问题主要是业财的一些操作习惯。
				lastTenantProfit, err := s.tenantsProfitRepository.GetLatestProfitByCode(ctx, row.DeliveryNo, row.ProfitCode, row.TenantCode)
				if err != nil {
					stark.Logger.Errorf(ctx, "GetLatestProfitByCode,err:%s", err.Error())
				}
				if subValue.SignType == 2 && lastTenantProfit.Id != 0 && row.StartTime.Time.Before(lastTenantProfit.EndTime.Time) {
					stark.Logger.Infof(ctx, "重新设置权益开始时间")
					row.StartTime = lastTenantProfit.EndTime
				}

				//剔除不存在的权益产品
				if row.ProfitCode != "" {
					profitList = append(profitList, row)
				}

			}
		}
	}
	return profitList
}

func (s *CreateTenantService) saveCreateTaskLog(ctx context.Context, request *pb.CreateTenantRequest) (bool, error) {
	//当不存在任务时，会新增任务
	effectiveCreateTask, err := s.tenantsCreateTaskRepository.GetTaskByTenantCode(ctx, request.TenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTenantByCode,err:%s", err.Error())
	}
	if effectiveCreateTask == nil || effectiveCreateTask.Id == 0 {
		effectiveCreateTask.TenantCode = request.TenantCode
		effectiveCreateTask.Status = constants.CreateTenantStatusReady
		effectiveCreateTask.TaskId = request.TaskId
		_, err := s.tenantsCreateTaskRepository.AddTenantsCreateTask(ctx, effectiveCreateTask)
		if err != nil {
			stark.Logger.Errorf(ctx, "AddTenantsCreateTask 新增租户创建任务,err:%s", err.Error())
		}
	}
	return true, nil
}

// RemoveTenant 销户
func (s *CreateTenantService) RemoveTenant(ctx context.Context, request *pb.RemoveTenantRequest) (*pb.RemoveTenantResponse, error) {
	resp := &pb.RemoveTenantResponse{
		TaskId: request.TaskId,
	}
	//token设置到缓存
	cacheKey := omp_remote.OmpServiceTokenCacheKey + request.TaskId
	redisClient, _ := cache.Redis()
	token, err := redisClient.Get(ctx, cacheKey)
	if err != nil {
		stark.Logger.Errorf(ctx, "获取cache失败,key:%s,err:%s", cacheKey, err.Error())
	}
	if token == "" {
		_, err = redisClient.Set(ctx, cacheKey, request.Authorization, true, omp_remote.OmpServiceTokenCacheKeyMaxExpireTime)
		if err != nil {
			stark.Logger.Errorf(ctx, "设置cache失败,key:%s,err:%s", cacheKey, err.Error())
		}
	}
	//日志
	requestJSON, err := json.Marshal(request)
	if err != nil {
		stark.Logger.Errorf(ctx, "结构体转string,err:%s", err.Error())
	}
	tjLogId, err := s.saveTjLog(ctx, "", request.TaskId, request.Authorization, request.TenantCode, string(requestJSON), constants.CreateTenantTjTypeRemove)
	if err != nil {
		resp.Success = false
		return resp, err
	}
	//销户
	_, err = s.tenantsRepository.DisableTenant(ctx, request.TenantCode)
	if err != nil {
		stark.Logger.Errorf(ctx, "租户销户,err:%s", err.Error())
	}
	resp.Success = true

	//更新响应结果
	respJSON, err := json.Marshal(resp)
	_, err = s.tenantsCreateTjLogRepository.UpdateResponseStatus(ctx, tjLogId, constants.CreateTenantStatusSuccess, string(respJSON))
	if err != nil {
		stark.Logger.Errorf(ctx, "UpdateResponseStatus,err:%s", err.Error())
	}

	//异步回调
	go func() {
		_, err := s.removeDatabaseSync(ctx, tjLogId, request.TenantCode, request.TaskId)
		if err != nil {
			stark.Logger.Errorf(ctx, "销户异步执行异常,err:%s", err.Error())
		}
	}()

	return resp, nil
}

func (s *CreateTenantService) CreateTenantCallback(ctx context.Context, request *pb.CreateTenantCallbackRequest, tjLogId int32) (*pb.CreateTenantCallbackResponse, error) {
	requestOmp := &omp_remote.CreateTenantCallbackRequest{
		TaskId: request.TaskId,
	}
	//获取任务状态
	getTaskStatusRequest := &pb.GetTaskStatusRequest{
		TaskId: request.TaskId,
	}
	getTaskStatus, err := s.GetTaskStatus(ctx, getTaskStatusRequest)
	//回调天际平台
	requestOmp.TaskStatus = getTaskStatus.TaskStatus
	requestOmp.TaskStatusDescription = getTaskStatus.TaskStatusDescription
	ompRes, err := omp_remote.NewOmpServiceRepo().CreateTenantCallback(ctx, requestOmp)
	if err != nil {
		stark.Logger.Errorf(ctx, "开库回调异常:%s", err.Error())
	}
	res := &pb.CreateTenantCallbackResponse{
		TaskStatus:            requestOmp.TaskStatus,
		TaskStatusDescription: requestOmp.TaskStatusDescription,
	}
	//更新回调结果 ，手动执行的回调,tjLogId=0，天际运营平台调用回调 tjLogId!=0
	requestOmpJson, err := json.Marshal(requestOmp)
	ompResJson, err := json.Marshal(ompRes)
	if err != nil {
		stark.Logger.Errorf(ctx, "结构体转string,err:%s", err.Error())
	}
	if tjLogId != 0 {
		_, err := s.tenantsCreateTjLogRepository.UpdateCallbackStatus(ctx, tjLogId, string(requestOmpJson), string(ompResJson))
		if err != nil {
			stark.Logger.Errorf(ctx, "UpdateCallbackStatus,err:%s", err.Error())
		}
	}

	//返回结果
	if ompRes.Code == 0 {
		return res, nil
	} else {
		return res, err
	}
}

// GetTaskStatus 获取任务状态
func (s *CreateTenantService) GetTaskStatus(ctx context.Context, request *pb.GetTaskStatusRequest) (*pb.GetTaskStatusResponse, error) {
	resp := &pb.GetTaskStatusResponse{}
	//取任务请求状态
	tjLogDetail, err := s.tenantsCreateTjLogRepository.GetTenantsCreateTjLog(ctx, request.TaskId)
	if err != nil {
		stark.Logger.Errorf(ctx, "GetTenantsCreateTjLog,err:%s", err.Error())
	}
	resp.TaskStatus = tjLogDetail.ResponseStatus

	//如果是开库，获取开库状态
	if tjLogDetail.Type == constants.CreateTenantTjTypeAdd {
		taskDetail, err := s.tenantsCreateTaskRepository.GetTaskByTenantCode(ctx, tjLogDetail.TenantCode)
		if err != nil {
			stark.Logger.Errorf(ctx, "GetTaskByTenantCode,err:%s", err.Error())
		}
		if taskDetail.Id != 0 {
			if taskDetail.Status == constants.CreateTenantStatusSuccess {
				resp.TaskStatus = constants.CreateTenantStatusSuccess
			} else if taskDetail.Status == constants.CreateTenantStatusFail {
				resp.TaskStatus = constants.CreateTenantStatusFail
			} else {
				resp.TaskStatus = constants.CreateTenantStatusReady
			}
			resp.TaskStatusDescription = taskDetail.ErrorMsg
		}
	}

	return resp, nil
}
